package com.shrct.businessprocess.purchase.impl;

import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.shrct.businessprocess.budget.RCBudget;
import com.shrct.businessprocess.product.RCProductSpecification;
import com.shrct.businessprocess.product.impl.RCProductSpecificationImpl;
import com.shrct.businessprocess.project.RCProjectMoney;
import com.shrct.businessprocess.purchase.RCBaseProductPurchaseBudget;
import com.shrct.businessprocess.purchase.RCBasePurchaseRequest;
import com.shrct.businessprocess.purchase.RCBudgetContract;
import com.shrct.businessprocess.purchase.RCBudgetContractItem;
import com.shrct.businessprocess.purchase.RCProductAndQuantity;
import com.shrct.businessprocess.purchase.RCProductDeliver;
import com.shrct.businessprocess.purchase.RCProductDeliverItem;
import com.shrct.businessprocess.purchase.RCProductPurchaseRequest;
import com.shrct.businessprocess.purchase.RCProductPurchaseRequestItem;
import com.shrct.businessprocess.purchase.impl.RCBudgetContractImpl;
import com.shrct.businessprocess.purchase.proxy.RCBudgetContractItemProxy;
import edu.fudan.mylang.common.NumberExtensions;
import edu.fudan.mylang.pf.BaseModelObject;
import java.util.Collection;
import java.util.List;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.Functions.Function2;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.StringExtensions;
import org.hibernate.annotations.DiscriminatorOptions;

@Entity
@DiscriminatorValue("RCBUDGETCONTRACTITEM_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "rcbudgetcontractitem")
public abstract class RCBudgetContractItemImpl extends BaseModelObject implements RCBudgetContractItem {
  public RCBudgetContractItemImpl() {
    super();
  }
  
  public RCBudgetContractItemImpl(final RCBudgetContract contract) {
    super();
    this.contract = contract;
  }
  
  @JoinColumn(name = "contract_id")
  @ManyToOne(targetEntity = RCBudgetContractImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCBudgetContract contract;
  
  public RCBudgetContract getContract() {
    return this.contract;
  }
  
  public RCBudgetContractItem setContract(final RCBudgetContract contract) {
    this.contract = contract;
    return this;			
    
  }
  
  private String title;
  
  public String getTitle() {
    return this.title;
  }
  
  public RCBudgetContractItem setTitle(final String title) {
    this.title = title;
    return this;			
    
  }
  
  @JoinColumn(name = "productSpec_id")
  @ManyToOne(targetEntity = RCProductSpecificationImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCProductSpecification productSpec;
  
  public RCProductSpecification getProductSpec() {
    return this.productSpec;
  }
  
  public RCBudgetContractItem setProductSpec(final RCProductSpecification productSpec) {
    this.productSpec = productSpec;
    return this;			
    
  }
  
  private Integer quantity;
  
  public Integer getQuantity() {
    return this.quantity;
  }
  
  public RCBudgetContractItem setQuantity(final Integer quantity) {
    this.quantity = quantity;
    return this;			
    
  }
  
  private Boolean isIncludeInContract;
  
  public Boolean getIsIncludeInContract() {
    return this.isIncludeInContract;
  }
  
  public RCBudgetContractItem setIsIncludeInContract(final Boolean isIncludeInContract) {
    this.isIncludeInContract = isIncludeInContract;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "amount", column = @Column(name = "price_amount") ), @AttributeOverride(name = "workaround", column = @Column(name = "price_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "exchange", joinColumns = @JoinColumn(name = "price_exchange") ) )
  private RCProjectMoney price = com.shrct.businessprocess.project.RCProjectMoney.create();
  
  public RCProjectMoney getPrice() {
    return this.price;
  }
  
  public RCBudgetContractItem setPrice(final RCProjectMoney price) {
    this.price = price;
    return this;			
    
  }
  
  public String getIdentifier() {
    String _code = this.productSpec.getCode();
    String _xifexpression = null;
    boolean _isNullOrEmpty = StringExtensions.isNullOrEmpty(this.title);
    if (_isNullOrEmpty) {
      _xifexpression = "";
    } else {
      String _plus = ("(" + this.title);
      String _plus_1 = (_plus + ")");
      _xifexpression = _plus_1;
    }
    String _plus_2 = (_code + _xifexpression);
    return _plus_2;
  }
  
  public Integer getDeliveredQuantity() {
    int _xblockexpression = (int) 0;
    {
      Collection<RCProductDeliver> _delivers = this.contract.getDelivers();
      final Function1<RCProductDeliver,Collection<RCProductDeliverItem>> _function = new Function1<RCProductDeliver,Collection<RCProductDeliverItem>>() {
          public Collection<RCProductDeliverItem> apply(final RCProductDeliver it) {
            Collection<RCProductDeliverItem> _items = it.getItems();
            return _items;
          }
        };
      Iterable<Collection<RCProductDeliverItem>> _map = IterableExtensions.<RCProductDeliver, Collection<RCProductDeliverItem>>map(_delivers, _function);
      Iterable<RCProductDeliverItem> _flatten = Iterables.<RCProductDeliverItem>concat(_map);
      final Function1<RCProductDeliverItem,Boolean> _function_1 = new Function1<RCProductDeliverItem,Boolean>() {
          public Boolean apply(final RCProductDeliverItem it) {
            RCProductSpecification _productSpec = it.getProductSpec();
            boolean _equals = Objects.equal(_productSpec, RCBudgetContractItemImpl.this.productSpec);
            return Boolean.valueOf(_equals);
          }
        };
      Iterable<RCProductDeliverItem> _filter = IterableExtensions.<RCProductDeliverItem>filter(_flatten, _function_1);
      final Function1<RCProductDeliverItem,Integer> _function_2 = new Function1<RCProductDeliverItem,Integer>() {
          public Integer apply(final RCProductDeliverItem it) {
            Integer _deliveredQuantity = it.getDeliveredQuantity();
            return _deliveredQuantity;
          }
        };
      Iterable<Integer> _map_1 = IterableExtensions.<RCProductDeliverItem, Integer>map(_filter, _function_2);
      final Function2<Integer,Integer,Integer> _function_3 = new Function2<Integer,Integer,Integer>() {
          public Integer apply(final Integer i1, final Integer i2) {
            int _plus = ((i1).intValue() + (i2).intValue());
            return Integer.valueOf(_plus);
          }
        };
      Integer result = IterableExtensions.<Integer>reduce(_map_1, _function_3);
      int _xifexpression = (int) 0;
      boolean _equals = Objects.equal(result, null);
      if (_equals) {
        _xifexpression = 0;
      } else {
        _xifexpression = result;
      }
      _xblockexpression = (_xifexpression);
    }
    return Integer.valueOf(_xblockexpression);
  }
  
  public Collection<RCProductDeliverItem> getDeliveredItems() {
    Collection<RCProductDeliver> _delivers = this.contract.getDelivers();
    final Function1<RCProductDeliver,Collection<RCProductDeliverItem>> _function = new Function1<RCProductDeliver,Collection<RCProductDeliverItem>>() {
        public Collection<RCProductDeliverItem> apply(final RCProductDeliver it) {
          Collection<RCProductDeliverItem> _items = it.getItems();
          return _items;
        }
      };
    Iterable<Collection<RCProductDeliverItem>> _map = IterableExtensions.<RCProductDeliver, Collection<RCProductDeliverItem>>map(_delivers, _function);
    Iterable<RCProductDeliverItem> _flatten = Iterables.<RCProductDeliverItem>concat(_map);
    final Function1<RCProductDeliverItem,Boolean> _function_1 = new Function1<RCProductDeliverItem,Boolean>() {
        public Boolean apply(final RCProductDeliverItem it) {
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, RCBudgetContractItemImpl.this.productSpec);
          return Boolean.valueOf(_equals);
        }
      };
    Iterable<RCProductDeliverItem> _filter = IterableExtensions.<RCProductDeliverItem>filter(_flatten, _function_1);
    List<RCProductDeliverItem> _list = IterableExtensions.<RCProductDeliverItem>toList(_filter);
    return _list;
  }
  
  /**
   * 如果该商品或者起关联产品已经请购过 则不允许删除
   */
  public Boolean canDelete() {
    RCBudget _budget = this.contract.getBudget();
    Collection<RCBasePurchaseRequest> _purchaseRequests = ((RCBaseProductPurchaseBudget) _budget).getPurchaseRequests();
    Iterable<RCProductPurchaseRequest> _filter = Iterables.<RCProductPurchaseRequest>filter(_purchaseRequests, RCProductPurchaseRequest.class);
    final Function1<RCProductPurchaseRequest,Collection<RCProductPurchaseRequestItem>> _function = new Function1<RCProductPurchaseRequest,Collection<RCProductPurchaseRequestItem>>() {
        public Collection<RCProductPurchaseRequestItem> apply(final RCProductPurchaseRequest it) {
          Collection<RCProductPurchaseRequestItem> _items = it.getItems();
          return _items;
        }
      };
    Iterable<Collection<RCProductPurchaseRequestItem>> _map = IterableExtensions.<RCProductPurchaseRequest, Collection<RCProductPurchaseRequestItem>>map(_filter, _function);
    Iterable<RCProductPurchaseRequestItem> _flatten = Iterables.<RCProductPurchaseRequestItem>concat(_map);
    final Function1<RCProductPurchaseRequestItem,Boolean> _function_1 = new Function1<RCProductPurchaseRequestItem,Boolean>() {
        public Boolean apply(final RCProductPurchaseRequestItem it) {
          RCProductSpecification _productSpec = it.getProductSpec();
          boolean _equals = Objects.equal(_productSpec, RCBudgetContractItemImpl.this.productSpec);
          return Boolean.valueOf(_equals);
        }
      };
    boolean _exists = IterableExtensions.<RCProductPurchaseRequestItem>exists(_flatten, _function_1);
    boolean _not = (!_exists);
    return Boolean.valueOf(_not);
  }
  
  /**
   * 待发货数量
   */
  public Integer getDeliverCandidatesQuantity() {
    Iterable<RCProductAndQuantity> _deliverCandidates = this.getDeliverCandidates();
    final Function1<RCProductAndQuantity,Integer> _function = new Function1<RCProductAndQuantity,Integer>() {
        public Integer apply(final RCProductAndQuantity it) {
          Integer _quantity = it.getQuantity();
          return _quantity;
        }
      };
    Iterable<Integer> _map = IterableExtensions.<RCProductAndQuantity, Integer>map(_deliverCandidates, _function);
    final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map, _function_1);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public Integer getInStockQuantity() {
    Iterable<RCProductAndQuantity> _inStockItems = this.getInStockItems();
    final Function1<RCProductAndQuantity,Integer> _function = new Function1<RCProductAndQuantity,Integer>() {
        public Integer apply(final RCProductAndQuantity it) {
          Integer _quantity = it.getQuantity();
          return _quantity;
        }
      };
    Iterable<Integer> _map = IterableExtensions.<RCProductAndQuantity, Integer>map(_inStockItems, _function);
    final Function2<Integer,Integer,Integer> _function_1 = new Function2<Integer,Integer,Integer>() {
        public Integer apply(final Integer i1, final Integer i2) {
          int _plus = ((i1).intValue() + (i2).intValue());
          return Integer.valueOf(_plus);
        }
      };
    Integer _reduce = IterableExtensions.<Integer>reduce(_map, _function_1);
    Integer _nullsafe = NumberExtensions.nullsafe(_reduce);
    return _nullsafe;
  }
  
  public RCBudgetContractItemProxy toProxy() {
    com.shrct.businessprocess.purchase.proxy.RCBudgetContractItemProxy proxy = new com.shrct.businessprocess.purchase.proxy.RCBudgetContractItemProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
